﻿#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>

//指针运算
//int my_strlen(char* str)
//{
//	int count = 0;
//	while (*str != '\0')
//	{
//		count++;
//		str++;//指针+整数
//	}
//	return count;
//}
//int main()
//{
//	int len = my_strlen("abcdef");
//	printf("%d\n", len);
//	return 0;
//}

//#define N_VALUES 5
//float values[N_VALUES];
//float* vp;
////指针+-整数；指针的关系运算
//for (vp = &values[0]; vp < &values[N_VALUES];)
//{
//	*vp++ = 0;
//}

//两个指针指向同一空间，指针类型是一致的
//int main()
//{
//	int arr[10] = {1,2,3,4,5,6,7,8,9,10 };
//	int n = &arr[9] - &arr[0];
//	printf("%d\n", n); //9
//	//指针-指针=两个指针之间的元素个数,+ or -（语法规定）
//	return 0;
//}

//int my_strlen(char* str)
//{
//	char* start = str;
//	while (*str != '\0')
//	{
//		str++;
//	}
//	return str-start; //指针-指针=元素个数
//}
//int main()
//{
//	int len = my_strlen("abcdef");
//	printf("%d\n", len);
//	return 0;
//}

//指针的关系运算
// //#define N_VALUES 5
//float values[N_VALUES];
//float* vp;
//for (vp = &values[N_VALUES]; vp > &values[0];)
//{
//	*--vp = 0;
//}
//for (vp = &values[N_VALUES - 1]; vp >= &values[0]; vp--)
//{
//	*vp = 0;
//}
//实际在绝大部分的编译器上是可以顺利完成任务的，然而我们还是应该避免这样写，因为标准并不保证
//它可行。
//标准规定：
//允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较，但是不允许与
//指向第一个元素之前的那个内存位置的指针进行比较。

//指针和数组
//指针的大小：4/8个字节，指针是存档地址的，地址存放需要多大空间，指针变量的大小就是多少
//数组的大小：取决数组的元素个数和每个元素的类型
//int main()
//{
//	int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
//	printf("%p\n", arr);  //00EFF718
//	printf("%p\n", &arr[0]); //00EFF718
//	return 0;
//}

//int main()
//{
//	int arr[10] = { 0 };
//	int* p = arr;//数组名是首元素的地址，&arr[0]
//	int i = 0;
//	//存放
//	for (i = 0; i < 10; i++)
//	{
//		*p = i + 1;
//		p++;
//	}
//	//打印
//	p = arr;
//	for (i = 0; i < 10; i++)
//	{
//		printf("%d ", *(p + i)); //1 2 3 4 5 6 7 8 9 10
//	}
//	return 0;
//}

//二级指针
//int main()
//{
//	int a = 10;
//	//一级指针
//	int* pa = &a;//pa是指针变量，用来存放地址，也向内存申请
//	//二级指针
//	int** ppa = &pa;
//	printf("%d\n", **ppa);
//	return 0;
//}

//指针数组是指针还是数组？
//答案：是数组。是存放指针的数组。
//数组我们已经知道整形数组，字符数组。
//int main()
//{
//	int a = 10, b = 20, c = 30;
//	int* arr[] = { &a,&b,&c };
//	int i = 0;
//	for (i = 0; i < 3; i++)
//	{
//		printf("%d ", *(arr[i]));  //10 20 30
//	}
//	return 0;
//}

//int main()
//{
//	char* arr[5]; //char*
//	char** p = arr;//&arr[0]---char**
//}

//int main()
//{
//	int arr1[] = { 1,2,3,4,5 };
//	int arr2[] = { 2,3,4,5,6 };
//	int arr3[] = {3,4,5,6,7 };
//	int* ptr []= { arr1,arr2,arr3 };
//	for (int i = 0; i < 3; i++)
//	{
//		for (int j = 0; j < 5; j++)
//		{
//			printf("%d ", ptr[i][j]);
//		}
//		printf("\n");
//	}
//	return 0;
//}
//void test(int arr[], int sz)
//{
//	for (int i = 0; i < 10; i++)
//	{
//		arr[i] = i;
//	}
//	for (int i = 0; i < 10; i++)
//	{
//		printf("%d ", arr[i]);//0,1,2,3,4,5,6,7,8,9
//	}
//}
//int main()
//{
//	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//	int* p = arr;
//	test(arr, 10);
//}

//int main()
//{
//	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
//	int i = 0;
//	for (i = 0; i < 10; i++)
//	{
//		printf("%d ", arr[i]);
//		printf("%d ", i[arr]);//两种写法一样
//	}
//	//*arr[i]-->*(arr+i)-->*(i+arr)--i[arr],取地址写法不同但是结果相同
//}

//int main()
//{
//	int arr[3][5];
//	//arr[i][j]=(*arr+i)[j]=*(*(arr+i)+j)
//}


//结构体
//结构的声明
//typedef struct Stu
//{
//	char name[20];//名字
//	int age;//年龄
//	char sex[5];//性别
//	char id[20];//学号
//}Stu；//分号不能丢

//结构体成员访问
//struct Book
//{
//	char name[20];
//	int price;
//};
//void print(struct Book* p)
//{
//	printf("%s %d\n", p->name,p->price);
//}
//int main()
//{
//	struct Book b1 = { "鹏哥C语言",60 };
//	struct Book b2 = { .price=80,.name="杭哥C++"};
//	//结构体变量.结构体成员
//	printf("%s %d\n", b1.name, b1.price);
//	printf("%s %d\n", b2.name, b2.price);
//	//结构体指针->结构体成员
//	//struct Book* p=&b1;
//	printf(&b1);
//	return 0;
//}

//结构体传参
//struct S
//{
//	int data[1000];
//	int num;
//};
//struct S s = { {1,2,3,4}, 1000 };
////结构体传参
//void print1(struct S s)
//{
//	printf("%d\n", s.num);
//}
//结构体地址传参
//void print2(struct S* ps)
//{
//	printf("%d\n", ps->num);
//}
//int main()
//{
//	print1(s);  //传结构体
//	print2(&s); //传地址
//	return 0;
//}
//上面的 print1 和 print2 函数哪个好些？
//答案是：首选print2函数。
//原因：
//函数传参的时候，参数是需要压栈的。
//如果传递一个结构体对象的时候，结构体过大，参数压栈的的系统开销比较大，所以会导致性能的
//下降。
//结论：
//结构体传参的时候，要传结构体的地址。


//作业
//int main()
//{
//	unsigned long pulArray[] = { 6,7,8,9,10 };
//	unsigned long* pulPtr;
//	pulPtr = pulArray;
//	*(pulPtr + 3) += 3;
//	printf("%d %d\n", * pulPtr, *(pulPtr + 3));//6 12
//}

//struct stu
//{
//	int num;
//	char name[10];
//	int age;
//};
//void fun(struct stu* p)
//{
//	printf("%s\n", (*p).name);  //wang
//	return;
//}
//int main()
//{
//	struct stu students[3] = { {9801,"zhang",20},
//							 {9802,"wang",19},
//					{9803,"zhao",18} };
//	fun(students + 1);
//	return 0;
//}

//字符串逆序
#include<string.h>
int main()
{
	char str[100] = { 0 };
	gets(str);
	int i, n;
	n = strlen(str);
	for (i = n - 1; i >= 0; i--)
		printf("%c", str[i]);
	return 0;
}

//#include<stdio.h>
//#include<stdlib.h>
//#include<string.h>
//int main()
//{
//	char str[100];
//	scanf("%s", str);
//	
//	int i = 0;
//	
//	int n = strlen(str);//获取字符串的长度
//	int  temp;
//	for (i = 0; i < (n / 2); i++)
//	{
//		temp = str[i];
//		str[i] = str[n - i - 1];
//		str[n - i - 1] = temp;
//	}
//	printf("%s\n", str);
//	return 0;
//}

//喝汽水，1瓶汽水1元，2个空瓶可以换一瓶汽水，给20元，可以多少汽水（编程实现）
//int main()
//{
//	int n = 0;
//	scanf("%d", &n);
//	printf("%d", 2*n-1);//找规律
//	return 0;
//}
//
//int main() {
//	int money = 0;
//	scanf("%d", &money);
//	int total = money;
//	int empty = money;
//	while (empty >= 2) {
//		total += empty / 2;
//		empty = empty / 2 + empty % 2;
//		// empty / 2空瓶换的饮料数，喝完之后的空瓶数empty % 2
//	}
//	printf("%d\n", total);
//	return 0;
//}